import plugin from "../../../lib/plugins/plugin.js"
import fs from "fs"
import path from "path"
import { execSync } from "child_process"
import settings from "../lib/settings.js"

export class Sync extends plugin {
  constructor() {
    super({
      name: "mirror-sync-plugin",
      dsc: "镜像同步插件",
      event: "message",
      priority: 5000,
      rule: [
        {
          reg: "^#镜像同步(.*)$",
          fnc: "sync",
          permission: "master",
        },
        {
          reg: "^#切回源\\s*(.*)$",
          fnc: "switchToSource",
          permission: "master",
        },
        {
          reg: "^#一键还原$",
          fnc: "restoreAll",
          permission: "master",
        },
        {
          reg: "^#查看所有源$",
          fnc: "listSources",
          permission: "master",
        },
        {
          reg: "^#查看配置源$",
          fnc: "listConfiguredSources",
          permission: "master",
        },
        {
          reg: "^#(sync|镜像)帮助$",
          fnc: "help",
          permission: "master",
        },
      ],
    })
  }

  // 获取配置
  getConfig() {
    return settings.getConfig("token")
  }

  // 扫描 plugins 目录下的 git 仓库
  async scanPlugins() {
    const pluginsPath = path.join(process.cwd(), "plugins")
    const plugins = []

    if (!fs.existsSync(pluginsPath)) {
      return plugins
    }

    const items = fs.readdirSync(pluginsPath)
    for (const item of items) {
      const itemPath = path.join(pluginsPath, item)
      const gitPath = path.join(itemPath, ".git")

      if (fs.existsSync(gitPath)) {
        try {
          // 获取当前 remote URL
          const remoteUrl = execSync("git remote get-url origin", {
            cwd: itemPath,
            encoding: "utf8",
          }).trim()

          plugins.push({
            name: item,
            path: itemPath,
            currentUrl: remoteUrl,
            originalUrl: null, // 将在匹配时设置
          })
        } catch (error) {
          logger.warn(`[镜像同步] 获取 ${item} 的远程地址失败: ${error.message}`)
        }
      }
    }

    return plugins
  }

  // 匹配镜像 URL（返回所有镜像地址）
  getMirrorUrls(pluginName, config) {
    const enabledRepos = config.enabled_repos || {}

    // 使用插件目录名匹配配置的 repo_name
    if (enabledRepos[pluginName] && enabledRepos[pluginName].dest_urls) {
      // 返回所有目标地址
      return enabledRepos[pluginName].dest_urls
    }

    return []
  }

  // 提取不带认证的 URL
  getCleanUrl(url) {
    return url.replace(/:\/\/[^@]*@/, "://")
  }

  // 根据插件目录名获取原始源地址
  getSourceUrl(pluginName, config) {
    const enabledRepos = config.enabled_repos || {}

    // 直接使用插件名匹配配置的 repo_name
    if (enabledRepos[pluginName] && enabledRepos[pluginName].source_url) {
      return enabledRepos[pluginName].source_url
    }

    return null
  }

  // 验证镜像仓库是否存在
  async verifyMirror(mirrorUrl, config) {
    try {
      // 构建带认证的 URL
      const authUrl = this.buildAuthUrl(mirrorUrl, config)

      // 使用 git ls-remote 验证仓库是否存在（超时120秒）
      execSync(`git ls-remote ${authUrl}`, {
        encoding: "utf8",
        timeout: 120000,
      })
      return true
    } catch (error) {
      return false
    }
  }

  // 构建带认证的 URL
  buildAuthUrl(url, config) {
    const variables = config.variables || {}
    const authVars = {
      GITHUB_USER: variables.GITHUB_USER,
      GITHUB_TOKEN: variables.GITHUB_TOKEN,
      GITCODE_USER: variables.GITCODE_USER,
      GITCODE_TOKEN: variables.GITCODE_TOKEN,
      CNB_USER: variables.CNB_USER,
      CNB_TOKEN: variables.CNB_TOKEN,
    }

    // 提取域名
    const match = url.match(/https?:\/\/([^\/]+)/)
    if (!match) {
      return url
    }

    const domain = match[1]

    // 检测是否为 GitHub 相关域名（包括各种子域名）
    if (
      domain.includes("github.com") ||
      domain.includes("githubusercontent.com") ||
      domain.includes("github.io")
    ) {
      const user = authVars.GITHUB_USER || ""
      const token = authVars.GITHUB_TOKEN
      if (token) {
        return url.replace(
          `https://${domain}`,
          `https://${encodeURIComponent(user)}:${encodeURIComponent(token)}@${domain}`,
        )
      }
    }

    // 检测 GitCode 域名
    if (domain.includes("gitcode.com")) {
      const user = authVars.GITCODE_USER || ""
      const token = authVars.GITCODE_TOKEN
      if (token) {
        return url.replace(
          `https://${domain}`,
          `https://${encodeURIComponent(user)}:${encodeURIComponent(token)}@${domain}`,
        )
      }
    }

    // 检测 CNB 域名
    if (domain.includes("cnb.cool")) {
      const user = authVars.CNB_USER || ""
      const token = authVars.CNB_TOKEN
      if (token) {
        return url.replace(
          `https://${domain}`,
          `https://${encodeURIComponent(user)}:${encodeURIComponent(token)}@${domain}`,
        )
      }
    }

    // 没有配置该平台的认证信息则返回原 URL
    return url
  }

  // 同步单个插件
  async syncPlugin(pluginInfo, config) {
    const { name, path: pluginPath, currentUrl } = pluginInfo

    // 使用插件目录名匹配镜像地址
    const mirrorUrls = this.getMirrorUrls(name, config)

    if (!mirrorUrls || mirrorUrls.length === 0) {
      return {
        name,
        success: false,
        message: `未找到匹配的镜像地址`,
        currentUrl,
        originalUrl: this.getSourceUrl(name, config),
      }
    }

    let lastError = null
    let usedMirror = null

    // 依次尝试每个镜像地址
    for (const mirrorUrl of mirrorUrls) {
      try {
        // 验证镜像仓库（强制验证）
        const isValid = await this.verifyMirror(mirrorUrl, config)
        if (!isValid) {
          lastError = new Error(`镜像仓库不存在或无法访问: ${mirrorUrl}`)
          continue
        }

        usedMirror = mirrorUrl

        // 构建带认证的 URL
        const authUrl = this.buildAuthUrl(mirrorUrl, config)

        // 修改 remote URL（使用带认证的 URL）
        execSync(`git remote set-url origin ${authUrl}`, {
          cwd: pluginPath,
          encoding: "utf8",
        })

        return {
          name,
          success: true,
          message: `同步成功，已切换到镜像 (使用镜像: ${mirrorUrl})`,
          currentUrl,
          mirrorUrl: authUrl, // 实际保存的是带认证的 URL
          originalUrl: this.getSourceUrl(name, config),
        }
      } catch (error) {
        lastError = error
        logger.warn(`[镜像同步] ${name} 使用镜像 ${mirrorUrl} 失败: ${error.message}`)
        // 继续尝试下一个镜像
      }
    }

    // 所有镜像都失败
    return {
      name,
      success: false,
      message: `所有镜像都失败${lastError ? `: ${lastError.message}` : ""}`,
      currentUrl,
      mirrorUrl: usedMirror,
      originalUrl: usedMirror ? this.getSourceUrl(name, config) : this.getSourceUrl(name, config),
    }
  }

  // 主要同步逻辑
  async sync(e) {
    const config = this.getConfig()

    if (!config || !config.enabled_repos || Object.keys(config.enabled_repos).length === 0) {
      return e.reply("⚠️ 未配置镜像仓库信息，请检查 config/token.yaml 文件")
    }

    // 扫描 plugins 目录
    const plugins = await this.scanPlugins()

    if (plugins.length === 0) {
      return e.reply("📁 未找到任何 git 仓库")
    }

    // 获取匹配的插件并设置原始地址
    const matchedPlugins = []
    for (const plugin of plugins) {
      // 使用插件目录名匹配
      const mirrorUrls = this.getMirrorUrls(plugin.name, config)
      if (mirrorUrls && mirrorUrls.length > 0) {
        // 保存原始源地址
        plugin.originalUrl = this.getSourceUrl(plugin.name, config)
        matchedPlugins.push(plugin)
      }
    }

    if (matchedPlugins.length === 0) {
      return e.reply("ℹ️ 未找到需要同步的插件仓库")
    }

    await e.reply(`🔄 开始同步 ${matchedPlugins.length} 个插件...`)

    // 同步所有匹配的插件
    const results = []
    for (const plugin of matchedPlugins) {
      const result = await this.syncPlugin(plugin, config)
      results.push(result)
    }

    // 整理结果
    const successCount = results.filter(r => r.success).length
    const failedCount = results.length - successCount

    let msg = `✅ 镜像同步完成\n\n`
    msg += `总计: ${results.length} | 成功: ${successCount} | 失败: ${failedCount}\n\n`

    // 显示失败的插件
    const failed = results.filter(r => !r.success)
    if (failed.length > 0) {
      msg += `❌ 失败的插件:\n`
      failed.forEach(r => {
        msg += `• ${r.name}: ${r.message}\n`
        if (r.originalUrl && this.getCleanUrl(r.originalUrl) !== this.getCleanUrl(r.currentUrl)) {
          msg += `  原始地址: ${r.originalUrl}\n`
        }
      })
      msg += `\n`
    }

    // 显示成功的插件
    const success = results.filter(r => r.success)
    if (success.length > 0) {
      msg += `✅ 成功的插件:\n`
      success.forEach(r => {
        msg += `• ${r.name}\n`
        // 隐藏认证信息显示给用户
        const cleanUrl = this.getCleanUrl(r.mirrorUrl)
        msg += `  当前镜像: ${cleanUrl}\n`
        if (r.originalUrl && this.getCleanUrl(r.originalUrl) !== this.getCleanUrl(r.mirrorUrl)) {
          msg += `  原始地址: ${r.originalUrl}\n`
          msg += `  切换命令: #切回源 ${r.name}\n`
        }
      })
      msg += `\n`
    }

    msg += `💡 提示: 如果需要切换回原始源地址，请使用命令: #切回源 <插件名>`

    await e.reply(msg.trim())
  }

  // 切换插件回原始源地址
  async switchToSource(e) {
    const pluginName = e.msg.replace(/^#切回源\s*/, "").trim()

    if (!pluginName) {
      return e.reply("⚠️ 请指定插件名称，例如: #切回源 yenai-plugin")
    }

    const config = this.getConfig()
    const pluginPath = path.join(process.cwd(), "plugins", pluginName)
    const gitPath = path.join(pluginPath, ".git")

    // 检查插件目录是否存在
    if (!fs.existsSync(pluginPath)) {
      return e.reply(`❌ 插件 "${pluginName}" 不存在`)
    }

    // 检查是否是 git 仓库
    if (!fs.existsSync(gitPath)) {
      return e.reply(`❌ 插件 "${pluginName}" 不是 git 仓库`)
    }

    try {
      // 查找原始源地址
      const originalUrl = this.getSourceUrl(pluginName, config)

      if (!originalUrl) {
        return e.reply(`❌ 插件 "${pluginName}" 未配置镜像信息`)
      }

      // 获取当前 remote URL
      const currentUrl = execSync("git remote get-url origin", {
        cwd: pluginPath,
        encoding: "utf8",
      }).trim()

      const cleanOriginalUrl = this.getCleanUrl(originalUrl)
      const cleanCurrentUrl = this.getCleanUrl(currentUrl)

      if (cleanOriginalUrl === cleanCurrentUrl) {
        return e.reply(`ℹ️ 插件 "${pluginName}" 当前已在源地址`)
      }

      // 构建带认证的 URL 并切换回原始地址
      const authOriginalUrl = this.buildAuthUrl(cleanOriginalUrl, config)
      execSync(`git remote set-url origin ${authOriginalUrl}`, {
        cwd: pluginPath,
        encoding: "utf8",
      })

      // 注意：不再自动拉取代码，需要用户手动执行 git pull

      await e.reply(`✅ 插件 "${pluginName}" 已切换回原始源地址\n📌 ${cleanOriginalUrl}`)
    } catch (error) {
      logger.error(`[镜像同步] 切换 ${pluginName} 回源失败: ${error.message}`)
      await e.reply(`❌ 切换失败: ${error.message}`)
    }
  }

  // 一键还原所有插件到原始源地址
  async restoreAll(e) {
    const config = this.getConfig()

    if (!config || !config.enabled_repos || Object.keys(config.enabled_repos).length === 0) {
      return e.reply("⚠️ 未配置镜像仓库信息，请检查 config/token.yaml 文件")
    }

    // 扫描 plugins 目录
    const plugins = await this.scanPlugins()

    if (plugins.length === 0) {
      return e.reply("📁 未找到任何 git 仓库")
    }

    // 查找需要还原的插件（使用插件名匹配）
    const pluginsToRestore = []
    for (const plugin of plugins) {
      const mirrorUrls = this.getMirrorUrls(plugin.name, config)
      const currentUrl = this.getCleanUrl(plugin.currentUrl)
      // 检查当前 URL 是否在镜像列表中
      if (mirrorUrls && mirrorUrls.some(url => this.getCleanUrl(url) === currentUrl)) {
        // 保存原始源地址
        plugin.originalUrl = this.getSourceUrl(plugin.name, config)
        pluginsToRestore.push(plugin)
      }
    }

    if (pluginsToRestore.length === 0) {
      return e.reply("ℹ️ 没有需要还原的插件")
    }

    await e.reply(`🔄 开始还原 ${pluginsToRestore.length} 个插件到原始源地址...`)

    const results = []

    // 依次还原每个插件
    for (const plugin of pluginsToRestore) {
      const { name, path: pluginPath, originalUrl } = plugin

      const cleanOriginalUrl = this.getCleanUrl(originalUrl)
      const cleanCurrentUrl = this.getCleanUrl(plugin.currentUrl)

      if (cleanOriginalUrl === cleanCurrentUrl) {
        results.push({
          name,
          success: true,
          message: `已在源地址`,
        })
        continue
      }

      try {
        // 构建带认证的 URL 并切换回原始地址
        const authOriginalUrl = this.buildAuthUrl(cleanOriginalUrl, config)
        execSync(`git remote set-url origin ${authOriginalUrl}`, {
          cwd: pluginPath,
          encoding: "utf8",
        })

        // 注意：不再自动拉取代码，需要用户手动执行 git pull

        results.push({
          name,
          success: true,
          message: `还原成功`,
          originalUrl,
        })
      } catch (error) {
        logger.error(`[镜像同步] 还原 ${name} 失败: ${error.message}`)
        results.push({
          name,
          success: false,
          message: `还原失败: ${error.message}`,
          originalUrl,
        })
      }
    }

    // 整理结果
    const successCount = results.filter(r => r.success).length
    const failedCount = results.length - successCount

    let msg = `✅ 一键还原完成\n\n`
    msg += `总计: ${results.length} | 成功: ${successCount} | 失败: ${failedCount}\n\n`

    // 显示失败的插件
    const failed = results.filter(r => !r.success)
    if (failed.length > 0) {
      msg += `❌ 失败的插件:\n`
      failed.forEach(r => {
        msg += `• ${r.name}: ${r.message}\n`
      })
      msg += `\n`
    }

    // 显示成功的插件
    const success = results.filter(r => r.success)
    if (success.length > 0) {
      msg += `✅ 成功的插件:\n`
      success.forEach(r => {
        msg += `• ${r.name}`
        if (r.originalUrl) {
          msg += `\n  源地址: ${this.getCleanUrl(r.originalUrl)}`
        }
        msg += `\n`
      })
    }

    await e.reply(msg.trim())
  }

  // 查看所有配置的源地址
  async listConfiguredSources(e) {
    const config = this.getConfig()

    if (!config || !config.enabled_repos || Object.keys(config.enabled_repos).length === 0) {
      return e.reply("⚠️ 未配置镜像仓库信息，请检查 config/token.yaml 文件")
    }

    let msg = `📋 镜像同步插件 - 源地址配置列表\n\n`

    const repos = Object.entries(config.enabled_repos)
    if (repos.length === 0) {
      msg += `ℹ️ 暂无配置`
      return e.reply(msg)
    }

    // 遍历所有配置的仓库
    for (const [repoName, repoConfig] of repos) {
      msg += `📦 ${repoName}\n`
      msg += `   源地址: ${repoConfig.source_url}\n`

      if (repoConfig.dest_urls && repoConfig.dest_urls.length > 0) {
        msg += `   镜像地址:\n`
        for (const mirrorUrl of repoConfig.dest_urls) {
          msg += `     • ${mirrorUrl}\n`
        }
      }
      msg += `\n`
    }

    msg += `💡 提示: 使用 #镜像同步 命令来同步所有配置的插件`

    await e.reply(msg.trim())
  }

  // 查看所有插件的实际远程源地址
  async listSources(e) {
    // 扫描 plugins 目录
    const plugins = await this.scanPlugins()

    if (plugins.length === 0) {
      return e.reply("📁 未找到任何 git 仓库")
    }

    let msg = `📦 镜像同步插件 - 插件远程源地址列表\n\n`

    // 显示所有插件的远程地址
    for (const plugin of plugins) {
      const cleanUrl = this.getCleanUrl(plugin.currentUrl)
      msg += `📦 ${plugin.name}\n`
      msg += `   当前地址: ${cleanUrl}\n`
      msg += `\n`
    }

    msg += `💡 提示: 使用 #镜像同步 命令来同步插件到镜像`

    await e.reply(msg.trim())
  }

  // 显示帮助信息
  async help(e) {
    const msg = `📖 镜像同步插件帮助\n\n` +
      `📋 可用命令:\n` +
      `• #镜像同步 - 同步所有配置的插件到镜像\n` +
      `• #切回源 <插件名> - 切换特定插件回源地址\n` +
      `• #一键还原 - 将所有镜像插件还原到源地址\n` +
      `• #查看配置源 - 查看配置文件中的源地址列表\n` +
      `• #查看所有源 - 查看所有插件的实际远程源地址\n` +
      `• #(sync|镜像)帮助 - 显示此帮助信息\n\n` +
      `💡 使用说明:\n` +
      `1. 首次使用前请先配置认证信息（私有仓库需要）\n` +
      `2. 同步后需要手动执行 git pull 更新代码\n` +
      `3. 支持多镜像自动故障转移\n\n` +
      `🔧 配置方式:\n` +
      `• 锅巴界面: 重启后打开锅巴界面配置\n` +
      `• 手动配置: 编辑 config/token.yaml 文件\n\n` +
      `📝 更多信息请查看 README.md`

    await e.reply(msg)
  }
}
